#ifndef __PVMVOICECACHING_H__
#define __PVMVOICECACHING_H__

#include "pvm/pvmapi.h"
#include "lib/pvmvoice.h"

#include "lib/memory/pvmmemory.h"
#include "lib/pvmcircularbuffer.h"
#include "lib/sys/common/pvmspinlock.h"

class PVMDataLinkedNuffer;

class PVMVoiceCaching : public IPVMVoice, public PVMAllocableObject
{
protected:
	PVMVoiceCaching(IPVMVoice* sourceVoice, pvm_uint minBufferLengthMS, pvm_uint maxBufferLengthMS, pvm_uint renderStepInMS);
	pvm_uint getBufferLengthInBytes(pvm_uint lengthInMS);
	pvm_uint getLengthInMS(pvm_uint lengthInSamples);
	void dbgMonUpdateBufferState(pvm_uint currentSize);
public:
	virtual ~PVMVoiceCaching();

	virtual void GetFormat(pvm_uint32 &samplesPerSecond, pvm_uint32 &bitsperSample, pvm_uint32 &chanels);
	virtual pvm_uint32 GetSamplesPerSecond();
	virtual pvm_uint32 GetBitsPerSample();
	virtual pvm_uint32 GetChanelsNum();

	virtual pvm_uint32 FillBuffer(void *buffer, pvm_uint32 numSamples);
	virtual void SetPause(pvm_bool pause);
	virtual pvm_bool GetPause();
	virtual pvm_bool IsAlive();
	virtual void DoDestroy();

	virtual void OnIdle();

	virtual void SetLoopCount(pvm_int32 loopCount);
	virtual pvm_int32 GetLoopCount();
	virtual pvm_bool SetLoopInSamples(pvm_int64 loopFrom, pvm_int64 loopTo);
	virtual pvm_bool GetLoopInSamples(pvm_int64 &loopFrom, pvm_int64 &loopTo);
	virtual pvm_bool GetLoopInMS(pvm_int32 &loopFrom, pvm_int32 &loopTo);

	virtual pvm_bool SetPositionMS(pvm_int32 position);
	virtual pvm_int32 GetPositionMS();

	virtual pvm_bool GetOption(const pvm_char* optionName, void* optionVal, pvm_uint32* optionSize);
	virtual pvm_bool SetOption(const pvm_char* optionName, void* optionVal, pvm_uint32 optionSize);

	static PVMVoiceCaching* Create(IPVMVoice* sourceVoice, pvm_uint minBufferLengthMS, pvm_uint maxBufferLengthMS, pvm_uint renderStepInMS);
protected:
	PVMSpinLock			lock;
	IPVMVoice*			srcVoice;
	PVMCircularBuffer*	cacheBuffer;
	pvm_uint8*			renderBuffer;
	pvm_uint			bufferLengthMsMin;
	pvm_uint			bufferLengthMsMax;
	pvm_uint			bufferLengthBytesMin;
	pvm_uint			bufferLockSizeMax;
	pvm_uint			bufferRenderSizeMax;

	PVMDataLinkedNuffer* nextFreeBuffer;
	PVMDataLinkedNuffer* firstRenderedBuffer;
	PVMDataLinkedNuffer* lastRenderedBuffer;
	PVMDataLinkedNuffer* currentPlayingBuffer;
	
	int callsBeforFill;
	int idleRenderCalls;
	int samplesFilledFromLastIdle;

	pvm_int dbgMonIdBufferVal;
	pvm_int dbgMonIdBufferUnderflow;
	pvm_int dbgMonIdBufferFetchError;
	pvm_int dbgMonIdBufferDecodeSize;
	pvm_int dbgMonIdBufferFilledPartially;
	pvm_int dbgMonIdBufferFillSize;
};


#endif
